package org.romzzz.gwtclassifieds.server.service;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;

/**
 * This class is in charge of encrypting passwords for safer storage.
 * Decipher is not part of the requirements.
 */
public class Encrypter {
	
	/**
	 *  number of iterations to generate the digest
	 */
	private static int iterations = 873;

	public static String encrypt(String stringToEncrypt) {
		try {
			return getBase64EncodedString(getIteratedDigest(getBytes(stringToEncrypt)));
		} catch (Exception e) {
			e.printStackTrace();
			return stringToEncrypt;
		}
	}
	
	public static boolean compareWithEncrypted(String rawString, String encryptedString) {
		return encryptedString.equals(encrypt(rawString));
	}
	
	/**
	 * Step 1 - convert to bytes using UTF-8
	 * 
	 * @param string the string to convert
	 * @return a byte array
	 * @throws UnsupportedEncodingException
	 */
	private static byte[] getBytes(String string) throws UnsupportedEncodingException {
		return string.getBytes("UTF-8");
	}
	
	/**
	 * Step 2 - get digest using MD5
	 * 
	 * @param bytes the byte array to create the digest from
	 * @return the digest
	 * @throws NoSuchAlgorithmException
	 */
	private static byte[] getDigest(byte[] bytes) throws NoSuchAlgorithmException {
		MessageDigest msgDigest = MessageDigest.getInstance("MD5");
		msgDigest.update(bytes);
		return msgDigest.digest();
	}
	
	/**
	 * Step 3 - repeat the digest process many times ({@link #iterations iterations})
	 * 
	 * @param bytes
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	private static byte[] getIteratedDigest(final byte[] bytes) throws NoSuchAlgorithmException {
		byte[] result = bytes;
		for (int i=0; i<iterations; i++) {
			result = getDigest(result);
		}
		return result;
	}
	
	/**
	 * Step 4 - encode bytes using base64
	 * 
	 * @param bytes the byte array to encode
	 * @return a base64-encoded String
	 */
	private static String getBase64EncodedString(byte[] bytes) {
		return Base64.encodeBase64String(bytes);
	}
	
}
